<?php

/**
 * WSB_Node_Page
 *
 * PHP version 5
 *
 * @copyright  2007 Zephir Software Design AG
 */
class WSB_Node_Page extends WSB_Node
{

	private static $_pages;
	private static $_tree;
	private static $_rootlineIds;

	/**
	 * Array von Cms_Model_PageLanguage Objekten
	 *
	 * @var array
	 */
	private static $_languageVariants;
	private static $_languages;
	private static $_isBuilded;

    /**
     * Build the page tree and store the tree in $_tree
     *
     * @return  void
     */
    public static function buildTree()
	{

    	// Schneller als Zend_Db_Table?
		$db = Zend_Db_Table_Abstract::getDefaultAdapter();
		$sql = 'SELECT * FROM page WHERE deleted=0 ORDER BY pid ASC, sort ASC';
		$pages = $db->fetchAll($sql);

		// Root erstellen, falls nicht vorhanden
		if(count($pages) === 0) {
			self::addRootNode();
			$pages = $db->fetchAll($sql);
		}

		self::$_pages = array();
		foreach($pages AS $page) {
			// Node-Objekt erstellen
			$node = new WSB_Node_Page();
			$node->fillThisPage($page);
			if(empty($node->pid)) {
				$node->parent = null;
				self::$_tree = $node;
			} else {
				if(array_key_exists($node->pid, self::$_pages)) {
					$parent = self::$_pages[$node->pid];
					if($parent instanceof WSB_Node_Page) {
						$parent->addChild($node);
						$node->parent = $parent;
					}
				}
			}
			self::$_pages[$node->id] = $node;
		}

		self::buildLanguageVariants();
		self::buildLanguages();
	}

	/**
	 * Parentseiten vererben die Sprachen an untergeordnete Seiten
	 *
	 * @param int $pageId
	 * @return array
	 */
	public function getLanguageVariants($pageId)
	{
		if(isset(self::$_pages[$pageId])) {
			$node = self::$_pages[$pageId];
			if($node instanceof WSB_Node_Page) {
				$pageLanguages = array();
				while($node->hasParent()) {
					if(isset(self::$_languageVariants[$node->getPageId()])) {
						$pageLanguages = self::$_languageVariants[$node->getPageId()];
						break;
					}
					$node = $node->getParent();
				}
				// Root-Node
				if(isset(self::$_languageVariants[$node->getPageId()])) {
					$pageLanguages = self::$_languageVariants[$node->getPageId()];
				}

				$_languages = array();
				foreach($pageLanguages AS $pageLanguage) {
					$_languages[] = self::$_languages->getRow($pageLanguage->language_id);
					/*
					if(array_key_exists($pageLanguage->language_id, self::$_languages)) {
						$_languages[] = self::$_languages[$pageLanguage->language_id];
					}
					*/
				}
				return $_languages;
			}
		}
		return array();
	}


	/**
	 * Gib das Template-Objekt zurueck.
	 *
	 * @param Integer $pageId
	 * @return Cms_Model_Template
	 */
	public function getTemplate($pageId)
	{
		if(isset(self::$_pages[$pageId])) {
			$node = self::$_pages[$pageId];
			if($node instanceof WSB_Node_Page) {
				$template_id = 0;
				// Durchlaufe den Tree bis zum Rootnode
				while($node->hasParent()) {
					if(intval($node->template_id) > 0) {
						// Rekursiv
						if(empty($node->template_not_recursive)) {
							break;
						// Nicht rekursiv -> Node Page Id muss mit der aufgerufenen
						// Seiten-ID ueberein stimmen
						} elseif($node->getId() == $pageId) {
							break;
						}
					}
					$node = $node->getParent();
				}
				// Ist der aktuellen Seite eine Template-ID zugeordnet?
				if(intval($node->template_id) > 0) {
					// Rekursiv oder nicht rekursiv (->Node Page Id muss mit der aufgerufenen
					// Seiten-ID ueberein stimmen)
					if(empty($node->template_not_recursive) || ($node->getId() == $pageId)) {
						$template_id = $node->template_id;
					}
				}
				if($template_id > 0) {
					$table = new Cms_Model_DbTable_Template();
					$select = $table->select();
					// Das Template muss sichtbar und darf nicht geloescht sein
					$select->where('id=?', $template_id);
					$select->where('deleted=?', 0);
					$select->where('hidden=?', 0);
					return $table->fetchRow($select);
				}
			}
		}
		return null;
	}

	/**
	 * @return void
	 */
	public static function buildLanguageVariants()
	{
		$table = new Cms_Model_DbTable_PageLanguage();
		foreach($table->fetchAll(null, 'language_id ASC') AS $row) {
			self::$_languageVariants[$row->page_id][$row->language_id] = $row;
		}
	}

	/**
	 * Erstelle das Language Rowset-Objekt.
	 * @return void
	 */
	public static function buildLanguages()
	{
		$table = new Cms_Model_DbTable_Language();
		$select = $table->select();
		$select->where('deleted=?', 0);
		self::$_languages = $table->fetchAll($select);
	}

	/**
	 * Kompletten Baum zurueckgeben
	 *
	 * @return WSB_Node_Page
	 */
	public static function getTree()
	{
		if(is_null(self::$_tree)) {
			self::buildTree();
		}
		return self::$_tree;
	}

	/**
	 * Fill $this with a row used in a DB query.
	 *
	 * @param Array $row	Coming from DB
	 */
	public function fillThisPage(array $row)
	{
		foreach($row AS $key=>$val) {
			$this->$key = $val;
		}
	}

	/**
	 * ID zureckgeben.
	 *
	 * @return integer
	 */
	public function getPageId()
	{
		return $this->id;
	}

	/**
	 * ID zurueckgeben. Alias fuer $this->getPageId()
	 *
	 * @return integer
	 */
	public function getId()
	{
		return $this->getPageId();
	}

	/**
	 * Parent ID zurueckgeben.
	 *
	 * @return integer
	 */
	public function getParentId()
	{
		return $this->pid;
	}

	/**
	 * @throws Exception
	 * @return string
	 */
	public function getUrlPathSegment()
	{
		$segment = '';
		/*
		if(!empty($this->alias)) {
			$segment = $this->alias;
		}
		*/
		if(!empty($this->title)) {
			$segment = $this->title;
		}
		else {
			$segment = $this->getId();
		}
		$segment = $this->makeUrlCompliantString($segment);
		if(empty($segment)) {
			throw new Exception('Invalid page name or page alias name!');
		} else {
			return $segment;
		}
	}

	/**
	 * Build a url compliant string
	 *
	 * @param string $str
	 * @return string
	 */
	private function makeUrlCompliantString($str)
	{
		$delimiter = '-';
		// translate special signs
		$from = array(
			'"', "'", '�', '�', '�', '�', '�', '�'
		);
		$to = array(
			'', '', 'ae', 'oe', 'ue', 'ae', 'oe', 'ue'
		);
		$str = strtolower(str_replace($from, $to, $str));
		// Alles entfernen, was keine Buchstaben oder Zahlen sind
		$str = preg_replace('#[^a-z0-9]#', $delimiter, $str);
		// mehrere Unterstriche zu einem
		$str = preg_replace('#'.$delimiter.'+#', $delimiter, $str);
		// Unterstriche am Anfang und Ende entfernen
		$str = preg_replace('#^'.$delimiter.'+|'.$delimiter.'+$#', '', $str);
		return $str;
	}

	/**
	 * Gib die Seite fuer eine bestimmte ID zurueck.
	 *
	 * @param integer $pageId
	 * @return Cms_Model_Page
	 */
	public function getPage($pageId)
	{
		$branch = self::getBranch($pageId);
		if($branch instanceof WSB_Node_Page) {
	        $data = array(
	            'table'   => new Cms_Model_DbTable_Page(),
	            'data'    => $branch->toArray(),
	            'stored'  => true
	        );
			return new Cms_Model_Page($data);
		}
		return null;
	}

	/**
	 * @param integer $pageId
	 * @return Cms_Model_Page
	 */
	public function getPageForFrontend($pageId)
	{
		$branch = self::getBranch($pageId);
		if($branch instanceof WSB_Node_Page) {
			// $feuser = WSB_Auth_Frontend::getInstance()->getIdentity();
			$i=0;
			$break = false;
			while(intval($branch->shortcut) > 0) {
				switch(intval($branch->shortcut)) {
					case Cms_Model_Page::SHORTCUT_TYPE_PAGE:
						if(!empty($branch->shortcut_page_id)) {
							$branch = self::getBranch($branch->shortcut_page_id);
						} else {
							$break = true;
						}
						break;
					case Cms_Model_Page::SHORTCUT_TYPE_FIRST_SUBPAGE:
						if($branch->hasChildren()) {
							$break = true;
							foreach($branch->getChildren() AS $child) {
								if($child instanceof WSB_Node_Page) {
									// Nur sichtbare und nicht geloeschte Seiten
									// beruecksichtigen.
									if(empty($child->hidden) && empty($child->deleted)) {

										// Nur Seiten beruecksichtigen, auf die der
										// Frontend Benutzer Zugriff hat.
										// $page = $this->getPage($child->id);
										// if($page->hasAccess($feuser)) {
											$branch = $child;
											$break = false;
											break;
										// }

									}
								}
							}
						} else {
							$break = true;
						}
						break;
				}

				if($break) {
					break;
				}

				// @todo: Moegliche Endlosschleife unterbrechen
				if($i>20) die('Error: Infinite loop in WSB_Node_Page::getPageForFrontend()');
				$i++;
			}
			return $this->getPage($branch->id);
		}
		return $this->getPage($pageId);
	}

	/**
	 * @param int $pageId
	 * @return WSB_Node_Page
	 */
	public static function getBranch($pageId)
	{
		if(is_null(self::$_tree)) {
			self::buildTree();
		}
		if(isset(self::$_pages[$pageId])) {
			return self::$_pages[$pageId];
		}
		return null;
	}

	/**
	 * @return string
	 */
	public function getLanguageVariantsAsString()
	{
		if(isset(self::$_languageVariants[$this->id])) {
			$str = '';
			$delim = ' ';
			foreach(self::$_languageVariants[$this->id] AS $pageLanguage) {
				$language = self::$_languages->getRow($pageLanguage->language_id);
				if($language instanceof Cms_Model_Language) {
				//if(isset(self::$_languages[$pageLanguage->language_id])) {
				//	$iso = self::$_languages[$pageLanguage->language_id]->iso;
					$iso = $language->iso;
					$str .= $delim . strtoupper($iso);
					$delim = ' ';
				}
			}
			return $str;
		}
		return null;
	}

	/**
	 * Erstelle den ROOT node.
	 * @return void
	 */
	public static function addRootNode()
	{
		$table = new Cms_Model_DbTable_Page();
		$row = $table->createRow();
		$row->pid = 0;
		$row->title = 'ROOT';
		$row->sort = 0;
		$row->hidden = 0;
		$row->nav_hide = 0;
		$row->template_not_recursive = 0;
		$row->save();
	}

	/**
	 * @param WSB_Node_Page $node
	 * @param integer $pageId
	 * @return boolean
	 */
	public static function isSubPage(WSB_Node_Page $node, $pageId)
	{
		while($node->hasParent()) {
			if($node->id === $pageId) {
				return true;
			}
			$node = $node->getParent();
		}
		return false;
	}

	/**
	 * Ist die Seite sichtbar?
	 * - nicht geloescht
	 * - nicht versteckt
	 * - im Menu sichtbar
	 *
	 * @return boolean
	 */
	public function isVisible()
	{
		//return !(bool)$this->hidden;
		return !(bool)($this->deleted || $this->hidden || $this->nav_hide);
	}

	/**
	 * @param WSB_Node_Page $node
	 * @return array
	 */
	public function getFegroupIdsRecursive(WSB_Node_Page $node)
	{
		$fegroupIds = array();
		$isCurrentPage = true;
		while($node->hasParent()) {
			if($node->fegroups != '') {
				if($isCurrentPage || (boolean)$node->fegroups_recursive) {
					$fegroupIds = array_merge($fegroupIds, WSB_Div::csvToArray($node->fegroups, ','));
				}
			}
			$node = $node->getParent();
			$isCurrentPage = false;
		}
		// Root
		if($node->fegroups != '') {
			if($isCurrentPage || (boolean)$node->fegroups_recursive) {
				$fegroupIds = array_merge($fegroupIds, WSB_Div::csvToArray($node->fegroups, ','));
			}
		}
		return $fegroupIds;
	}

	/**
	 * @param integer $pageId
	 * @return array
	 */
	public function getRootlinePageIds($pageId)
	{
		$pageId = intval($pageId);
		if($pageId < 1) {
			return array();
		}
		if(!is_array(self::$_rootlineIds)) {
			self::$_rootlineIds = array();
		}
		if(array_key_exists($pageId, self::$_rootlineIds)) {
			return self::$_rootlineIds[$pageId];
		} else {
			$rootline = array();
			$node = self::getBranch($pageId);
			while(($node instanceof WSB_Node_Page) && $node->hasParent()) {
				$rootline[] = $node->getPageId();
				$node = $node->getParent();
			}
			$rootline[] = $node->getPageId();
			self::$_rootlineIds[$pageId] = $rootline;
			return $rootline;
		}
	}

	/**
	 * @return boolean
	 */
	public function hasVisibleChildren()
	{
		$visible = false;
		foreach($this->getChildren() AS $child) {
			if($child->isVisible()) {
				$visible = true;
				break;
			}
		}
		return $visible;
	}

}
